<?php
namespace App\Libs;

use \GatewayWorker\Lib\Gateway;

class Utility{
	public $liqtype = array(
		1 => '发红包',
		2 => '抢红包',
		3 => '给玩家发红包',
		4 => '收到玩家发来的红包',
		5 => '手续费',
        6 => '红包超时退回',
        7 => '抢到的红包',
        8 => '门票',
        9 => '(赢家)退回红包',
        10 => '抽水',
        11 => '红包赢利',
        12 => '传红包给玩家',
        13 => '传红包手续费',
        14 => '收到玩家传来的红包',
        15 => '创建红包',
        16 => '预投注余款退回',
        17 => '聊天室发红包',
        18 => '聊天室抢到的红包',
        19 => '退回聊天室红包未抢完',
        20 => '提现',
        21 => '充值',
	);
	private $db;
    private $redis;
	
	public $redisPrefix = array(
		# 所有可用的游戏列表
		'GLAS' => 'game_list_all',
		# 单个游戏的参数和赔率参数
		'GPOP' => 'games_paras_odds_',
		# 所有可用的聊天室列表
        'CRAS' => 'chat_rooms_all',
		# 取单个聊天室的参数 getRoomParas
		'CRLP' => 'chat_rooms_',
		# 聊天室白名单列表
        'CRWL' => 'chat_rooms_whitelist_',
		# 聊天室黑名单列表
		'CRBL' => 'chat_rooms_blacklist_',
		# 取单个游戏的参数不包括赔率
		'GIFP' => 'games_item_forid_',
        # 系统参数
        'SYSP' => 'games_sys_paras_',
        'SOSUM' => 'chat_game_online',
	);
	public function __construct($db, $redis)
    {
        $this->db = $db;
        $this->redis = $redis;
    }
    # region Redis操作

    /**
     * 取Redis的值
     * @param $Redis object redis对象
     * @param $key string 要取值的redis字段名
     * @return mixed string|ing|array
     */
    public function redisGet($key){
        $value = $this->redis->get($key);
        $value_serl = @unserialize($value);
        if(is_object($value_serl)||is_array($value_serl)){
            return $value_serl;
        }
        return $value;
    }

    /**
     * 设置Redis数据
     * @param $Redis object redis对象
     * @param $key string 字段名
     * @param $value key对应的值（string|int|array）
     * @return mixed
     */
    public function redisSet($key, $value){
        if(is_object($value)||is_array($value)){
            $value = serialize($value);
        }
        return $this->redis->set($key,$value);
    }
    /**
     * 设置有时效性的Redis数据
     * @param $Redis object redis对象
     * @param $key string 字段名
     * @param $value key对应的值（string|int|array）
     * @param $value int 过期时间（秒）
     * @return mixed
     */
    public function redisSetEx($key, $value, $expire = 86400){
        if(is_object($value)||is_array($value)){
            $value = serialize($value);
        }
        return $this->redis->setex($key,$expire,$value);
    }

    /**
     * 检测LIST虽否存在对应的值
     * @param $redis object Redis对象
     * @param $key string 要查找的Redis键名
     * @param $value string 要检测的键值
     * @param int $Addition_subtraction 统计列表时是否加减总数
     * @return bool
     */
    public function existsRedisKey($key, $value)
    {
        $isHaveNuo = false;
        $_total = $this->redis->llen($key);
        $redis_key_index = 0;
        $redis_key_count = $_total;
        while($redis_key_index < $redis_key_count){
            $redis_key_item = $this->redis->lindex($key, $redis_key_index);
            if($redis_key_item == $value)
            {
                $isHaveNuo = true;
            }
            $redis_key_index++;
        }
        return $isHaveNuo;
    }
    public function roundFromRedisKey($key)
    {
        $key_count = $this->redis->llen($key);
        $key_index = mt_rand(0, $key_count);
        $result = $this->redis->lindex($key, $key_index);
        # 从KEY中删除
        $this->redis->lrem($key, $key_index, 1);
        return $result;
    }
    # endregion

    # region 001 通用过程
    /**
     * 资金帐变的类型
     * @return array
     */
    public function coinlog_liqtype(){
        return $this->liqtype;
    }
	/**
     * 生成随机长度的数字、字母组合
	 * 函数encrypt($string,$operation,$key)
	 * @param string $string 需要加密解密的字符串
	 * @param string $operation 判断是加密还是解密，E表示加密，D表示解密；
	 * @param string $key 密匙。
	 */
	public function randString($length=4){
		// 密码字符集，可任意添加你需要的字符
		$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
		$password = '';
		for ( $i = 0; $i < $length; $i++ )
		{
		// 这里提供两种字符获取方式
		// 第一种是使用 substr 截取$chars中的任意一位字符；
		// 第二种是取字符数组 $chars 的任意元素
		// $password .= substr($chars, mt_rand(0, strlen($chars) – 1), 1);
			$password .= $chars[ mt_rand(0, strlen($chars) - 1) ];
		}
		return $password;
	}
	//加密解密字符串
	public function encrypt($string,$operation,$key=''){
		$key=md5($key);
		$key_length=strlen($key);
		$string=$operation=='D'?base64_decode($string):substr(md5($string.$key),0,8).$string;
		$string_length=strlen($string);
		$rndkey=$box=array();
		$result='';
		for($i=0;$i<=255;$i++){
			$rndkey[$i]=ord($key[$i%$key_length]);
			$box[$i]=$i;
		}
		for($j=$i=0;$i<256;$i++){
			$j=($j+$box[$i]+$rndkey[$i])%256;
			$tmp=$box[$i];
			$box[$i]=$box[$j];
			$box[$j]=$tmp;
		}
		for($a=$j=$i=0;$i<$string_length;$i++){
			$a=($a+1)%256;
			$j=($j+$box[$a])%256;
			$tmp=$box[$a];
			$box[$a]=$box[$j];
			$box[$j]=$tmp;
			$result.=chr(ord($string[$i])^($box[($box[$a]+$box[$j])%256]));
		}
		if($operation=='D'){
			if(substr($result,0,8)==substr(md5(substr($result,8).$key),0,8)){
				return substr($result,8);
			}else{
				return'';
			}
		}else{
			return str_replace('=','',base64_encode($result));
		}
	}
	/**
	* 检测数组中是否包含KEY这个键
	* @param string $key 键名
	* @param array $arr 待检测的数组
	* @param string $dataType 返回值的类型 默认是数值型
	* @param object $result 返回按$isNumeric指定的类型值
	*/
	public function existsKeyInArray($key,$arr,$dataType='N',$default=0){
		$result = '';
		if(is_array($arr) && count($arr)>0 && array_key_exists($key,$arr)){
			switch($dataType){
				case 'N':
					$result = intval($arr[$key]);
					break;
				case "S": //字符型
					$result = strval($arr[$key]);
					break;
				case 'D': //日期型 2017-10-11
					$result = date('Y-m-d',strtotime($arr[$key]));
					break;
				case 'F': //货币数字
					$result = floatval($arr[$key]);
					break;
			}
		}else{
			switch($dataType){
				case 'N':
					$result = $default ? $default : 0;
					break;
				case "S": //字符型
					$result = $default ? $default : '';
					break;
				case 'D': //日期型 2017-10-11
					$result = $default ? $default : '';
					break;
				case 'F': //货币数字
					$result = $default ? $default : 0;
					break;
			}
		}
		return $result;
	}

    /**
     * 格式化金币为两位小数
     * @param $coin
     * @return string
     */
	public function formatCoin($coin)
    {
        return number_format($coin, 2, '.', '');
    }
    /**
     * 格式化时间截 - 聊天时间展示
     * @param $times int 时间截
     * @return false|string
     */
    public function formatTimes($times)
    {
        echo  date('H:i:s', $times) . "\n";
        $w_begin = mktime(0, 0 , 0,date("m"),date("d")-date("w")+1,date("Y"));
        $w_end = mktime(0, 0 , 0,date("m"),date("d")-date("w")+7,date("Y"));

        $wu_begin = mktime(0,0,0,date('m'),date('d')-date('w')+1-7,date('Y'));
        $wu_end = mktime(0,0,0,date('m'),date('d')-date('w')+7-7+1,date('Y'));

        $result = date('Y-m-d- H:i:s', $times);
        $limit = time() - $times;

        $day_begin = strtotime(date('Y-m-d',time()));
        $day_end = $day_begin + 24 * 3600;

        if($day_begin < $times && $day_end > $times){
            $result = date('H:i:s', $times);
        }elseif(($day_begin - 86400) < $times && ($day_end - 86400) > $times){
            //昨天
            $result = '昨天 '.date('H:i:s', $times);
        }elseif(($day_begin - 86400 - 86400) < $times && ($day_end - 86400 -86400) > $times){
            //前天
            $result = '前天 '.date('H:i:s', $times);
        }elseif($times > $w_begin && $times < $w_end){
            //本周
            $w = "星期" . mb_substr( "日一二三四五六",date("w", $times),1,"utf-8" );
            $result = $w.' '.date('H:i:s', $times);
        }elseif ($times > $wu_begin && $times < $wu_end){
            //上周
            $w = "上周" . mb_substr( "日一二三四五六",date("w", $times),1,"utf-8" );
            $result = $w.' '.date('H:i:s', $times);
        }else{
            $result = date('Y-m-d H:i:s', $times);
        }
        return $result;
    }

    /**
	* 红包算法
	* @param float $total 红包总金额
	* @param int $num 需要分配的个数
	*/
	public function redPacketRound($total,$num){
		//$total=10;//红包总额
		//$num=8;// 分成8个红包，支持8人随机领取
		$min=0.01;//每个人最少能收到0.01元
		$datas = array();
		for ($i=1;$i<$num;$i++)  
		{  
			$safe_total=($total-($num-$i)*$min)/($num-$i);//随机安全上限  
			$money=mt_rand($min*100,$safe_total*100)/100;  
			$total=$total-$money;  
			//echo '第'.$i.'个红包：'.$money.' 元，余额：'.$total.' 元 <br/>';
			$datas[$i] = array(
				'coin' => $this->formatCoin($money, 2),
			);
		}  
		$datas[$num] = array(
				'coin' => $this->formatCoin($total),
			);
		return $datas;
	}



	public function replaceKeys($redis, $db, $string){
	    $currency_unit = $this->getSystemParam($redis, $db, 'currencyName', '金币');
        $website_name = $this->getSystemParam($redis, $db, 'website_name', '抢红包');
        $webimgsurl = $this->getSystemParam($redis, $db, 'webimgsurl', '抢红包');
        $string = str_replace('{currency_unit}',$currency_unit, $string);
	    $string = str_replace('{website_name}',$website_name, $string);
        $string = str_replace('{webimgsurl}',$webimgsurl, $string);
	    return $string;
    }
    /**
     * 检测红包是否有出现指定的尾数，如果没有即重新生成
     * @param $roundRedPackets array 已生成好的红包数据
     * @param $mantissa string|int 指定要出现的尾数
     */
	public function existsShowMantissa($roundRedPackets, $mantissa)
    {
        $isShow = false;
        foreach ($roundRedPackets as $v)
        {
            $current_mantissa = substr($v['coin'], -1);   //小数点后二位
            if($current_mantissa == $mantissa){
                $isShow = true;
                break;
            }
        }
        return $isShow;
    }

    /**
     * 取系统参数值
     * @param $redis object redis对象
     * @param $db object 数据库连接对象
     * @param $keyName string 要查找的系统参数name
     * @param $defaultValue string 没有定义时的默认值
     * @return mixed
     */
    public function getSystemParam($redis, $db, $keyName, $defaultValue)
    {
        $redis_key = $this->redisPrefix['SYSP'].$keyName;
        if($redis->exists($redis_key))
        {
            $result = $this->redisGet($redis, $redis_key);
        }else {
            $data = $db->column("SELECT `value` FROM `rp_params` WHERE `name`='{$keyName}'");
            $result = $data[0];
            if(empty($result)) $result = $defaultValue;
            $this->redisSet($redis, $redis_key, $result);
        }
        return $result;
    }

    /**
     * 随机抽取数组中的一行数据，并删除当前数组行后返回被抽取到的数值及重新组合后的数据
     * @param $arr array 需要处理的数组
     * @return array
     */
	public function getRedPacketFromArray($arr)
    {
        $result = array(
            'coin' => 0,
            'redpackets' => array(),
        );
        if(count($arr)>=1) {
            $key = array_rand($arr, 1);
            $value = $arr[$key]['coin'];
            unset($arr[$key]);
            $result = array(
                'coin' => $value,
                'redpackets' => $arr,
            );
        }
        return $result;
    }

    /**
     * 组装批量更新的SQL语句
     * @param $tableName string 要更新的表名
     * @param $keyFieldName string 表达式的关键字段名
     * @param $idsAndvalue array 对应关键字段的值和要更新后的值(array('0'=>array('id'=>1,'value'=>100)))
     * @return string
     */
    public function batchUpdateTable($tableName,$keyFieldName,$idsAndvalue)
    {
        $update_sql = "UPDATE `{$tableName}` SET ";
        $set_key = array();
        $set_value = array();
        $ids = "0";
        foreach ($idsAndvalue as $k=>$v) {
            $ids .= ",".$v[$keyFieldName];
            foreach ($v['value'] as $key=>$val)
            {
                $set_key[$key] = "`{$key}`= CASE `{$keyFieldName}`";
                $count_val = count($val);
                if(!isset($set_value[$key])) $set_value[$key] = "";
                for ($i=0;$i<$count_val;$i++)
                {
                    $set_value[$key] .= " WHEN {$v[$keyFieldName]} THEN '{$val}'";
                }
            }
        }
        //重新组装SQL
        foreach ($set_key as $key=>$val){
            $update_sql .= $val . $set_value[$key] . ' END,';
        }
        $update_sql = substr($update_sql, 0, -1);
        $update_sql .= " WHERE id IN({$ids})";
        return $update_sql;
    }

    /**
     * 二维数组根据$sortKey字段排序
     * @param $arr 要排序的二维数组
     * @param $sortKey 排序字段
     * @param string $direction 排序方向（DESC 降序；ASC 升序）
     * @return array
     */
    public function sortArray($arr, $sortKey, $direction = "ASC")
    {
        $arrSort = array();
        foreach($arr AS $uniqid => $row){
            foreach($row AS $key=>$value){
                $arrSort[$key][$uniqid] = $value;
            }
        }
        array_multisort($arrSort[$sortKey], constant("SORT_".$direction), $arr);
        return $arr;
    }

    /**
     * 取表中表达式的一列的值
     * @param $db 数据库连接指针
     * @param $tableName 表名
     * @param $fieldName 要返回值的字段名
     * @param $whereTxt 表达式
     * @param $defaultValue 默认值
     * @return mixed
     */
    public function getColValue($db, $tableName, $fieldName, $whereTxt)
    {
        $result = $db->query("SELECT `{$fieldName}` FROM `{$tableName}` WHERE {$whereTxt}");
        return $result;
    }

	public function totalTableRowsCount($db, $sql){
        $sql_total = str_replace('~field~', 'COUNT(1) AS __total', $sql);
        $sql_total = str_replace('~limit~', '', $sql_total);
        $sql_total = str_replace('~order~', '', $sql_total);
        $db_total = $db->row($sql_total);
        $total = $db_total['__total'];
        return $total;
    }
	
    /**
     * 按SQL语句来取数据
     * @param $sql string 执行的SQL语句
     * @param $args array 参数数组，各项数值请参阅以下说明
     * @param $field string 要搜索的字段
     * @param $skip int 搜索当前的开始页数
     * @param $pagesize int 每页显示的行数
     * @param $order SQL的ORDER条件
     */
    public function  getTableRows($db, $sql, $args)
    {
        $total = self::totalTableRowsCount($db, $sql);
        $skip = (intval($args['page_current']) - 1) * $args['pagesize'];
        $pagesize = intval($args['pagesize']);

        $sql = str_replace('~field~', $args['field'], $sql);
        $sql = str_replace('~limit~', 'LIMIT ' . $skip . ',' . $pagesize, $sql);
        $sql = str_replace('~order~', $args['order'], $sql);
		
		// print_r($sql);
		
        $datas = $db->query($sql);

        return array(
            'datas' => $datas,
            'total' => $total,
        );
	}
	
	// 获取数据列表最大页码
	public function get_maxpage($psize,$total) {
		$page_max = $total>0 && $psize>0 ? ceil($total / $psize) : 1;
		return $page_max ? $page_max : 1;
	}
	public function get_url_args($paras, $mastArgs)
	{
        $args = array();
		foreach($mastArgs as $key=>$val)
		{
			$args[$val] = self::existsKeyInArray($val, $paras, 'S');
		}
		// print_r($args);
        return $args;
	}
	public function get_page_args($paras, $mastArgs)
	{
		$page_args = array();
		foreach($mastArgs as $key=>$val)
		{
			if (!empty($paras[$val])) $page_args[$val] = $paras[$val];
		}
		$page_args['pc'] = self::existsKeyInArray('pc',$paras,'N', 1);
        return $page_args;
	}
    #endregion


    #region 取游戏的相关数据

    /**
     * 在二维数组中查找指定$key并返回指定$resultKey的值
     * @param $arr  二维数组
     * @param $key  要查找的数组列
     * @param $value 查找的列的值
     * @param $resultKey 要返回数组中的列名
     * @return int
     */
    public function getOddsWinSort($arr, $key, $value, $resultKey)
    {
        $result = 0;
        foreach($arr as $keyp=>$valuep){
            if($valuep[$key]==$value){
                $result = $valuep[$resultKey];
            }
        }
        return $result;
    }
    /**
     * 生成当前游戏类型的期号
     * @param $db_id object 数据库对象
     * @param $game_id int 游戏类型
     * @return string
     */
    public function getIssue($redis, $db, $gameid){
        $redis_key = 'games_issue_' . $gameid . '_count';
        $redis_key_date = 'games_issue_' . $gameid . '_createdate';
        $issue_nums_len = 6;
        $issue_nums = 1000000; //要保留的期号长度,当前数字少一位数
        $nowdate = strval(date('Ymd'));
        # 如果Key存在且创建的日期是今天即从Redis缓存中取期数
        //if($redis->exists($redis_key) && $nowdate==$redis->get($redis_key_date))
        //{
        //    $redis_issue = $redis->get($redis_key);
        //    $_issue = substr($redis_issue,-1,$issue_nums_len);
        //    $sourceNumber = intval($_issue) + 1;
        //    $newNumber = substr(strval($sourceNumber + $issue_nums), 1, 6);
        //}else {
            $beginTimes = mktime(0, 0, 0, date('m'), date('d'), date('Y'));
            $endTimes = $beginTimes + 86400;
            $sql = "SELECT (COUNT(1)+1) AS _TOTAL FROM `rp_bets` WHERE `begintimes`>={$beginTimes} AND `begintimes`<={$endTimes} AND `gameid`={$gameid}";
            $issue_db = $db->row($sql);
            $sourceNumber = $issue_db['_TOTAL'];
            $newNumber = substr(strval($sourceNumber + $issue_nums), 1, 6);
        //}
        $issue = date('Ymd') . $gameid . $newNumber;
        # 写入Redis
        $this->redisSet($redis, $redis_key, $issue);
        $this->redisSet($redis, $redis_key_date, $nowdate);
        return $issue;
    }

    /**
     * 找出还在抢的红包数据（进行中的）
     * @param $db_id object 数据库对象
     * @param $game_id int 游戏类型
     */
    public function getGrabingRedpacket($db, $game_id)
    {
        $where = "(overtime - (UNIX_TIMESTAMP() - begintimes)) > 0 AND b.`uid`=u.`uid` AND b.`state`=0 AND b.`need`>b.`cur` AND b.`gameid`={$game_id}";
        $fields = "b.`id`,b.`issue`,b.`mantissa`,b.`nickname`,b.`need`,b.`cur`,b.`coin`,b.`begintimes`,b.`overtime`,u.`avatar`";
        $sql = "SELECT {$fields} FROM `rp_bets` b,`rp_users` u WHERE {$where}";
        $result = $db->query($sql);
        return $result;
    }

    /**
     * 本期红包用户列表
     * @param $db
     * @param $issue
     * @return mixed
     */
    public function getGrabUserList($db,$issue)
    {
        $sql = "SELECT b.`id`,b.`uid`,b.`issue`,b.`gameid`,b.`cardtype`,b.`odds`,b.`mantissa`,b.`coin`,b.`times`,b.`ticket`,b.`winerprofit`,b.`profit`,u.`uid` AS userid,u.`nickname`,u.`avatar` ";
        $sql .="FROM `rp_betslog` b,`rp_users` u WHERE u.`uid`=b.`uid` AND b.`issue`='{$issue}' ORDER BY b.`times` ASC";
        $grabusers = $db->query($sql);

        return $grabusers;
    }

    /**
     * 已完成的指定期数红包
     * @param $redis
     * @param $db
     * @param $issue
     * @return mixed
     */
    public function getGameForIssueIsEnd($redis, $db, $issue)
    {
        $redis_key = 'games_item_for_'.$issue;
        if($redis->exists($redis_key))
        {
            $data = $this->redisGet($redis, $redis_key);
        }else {
            $sql = "SELECT b.`id`,b.`uid`,b.`issue`,b.`gameid`,b.`cardtype`,b.`odds`,b.`mantissa`,b.`coin`,b.`times`,b.`ticket`,b.`winerprofit`,b.`profit`,u.`uid` AS userid,u.`nickname`,u.`avatar` ";
            $sql .="FROM `rp_betslog` b,`rp_users` u WHERE u.`uid`=b.`uid` AND b.`issue`='{$issue}' ORDER BY b.`times` ASC";
            $data['grabusers'] = $db->query($sql);
            $sql = "SELECT * FROM `rp_bets` WHERE `issue`='{$issue}'";
            $data['datas'] = $db->row($sql);
            $this->redisSetEx($redis, $redis_key, $data);
        }
        return $data;
    }
    //取游戏的参数不包括赔率
    public function getGameForID($redis, $db, $game_id)
    {
        $redis_key = 'games_item_forid_'.$game_id;
        if($redis->exists($redis_key))
        {
            $data = $this->redisGet($redis, $redis_key);
        }else {
            $where = "`id`={$game_id}";
            $fields = "id, title, func, establishcost, ishavebanker, establishcoin, manymen, custombetscoin, betscoinlist, minbetcoin, maxbetcoin, overtime, maxodds, state";
            //$fields = "`id`,`title`,`funcname`,`minmultiple`,`overtime`,`bets`,`ticket`,`bankerwon`,`needuser`";
            $sql = "SELECT {$fields} FROM `rp_games` WHERE {$where}";
            $data = $db->row($sql);
            $this->redisSet($redis, $redis_key, $data);
        }
        return $data;
    }
    /**
     * 取所有状态为可用的游戏
     * @param $db 数据库连接对象
     * @return mixed
     */
    public function getGameList($redis, $db)
    {
        $redis_key = $this->redisPrefix['GLAS'];
        if($redis->exists($redis_key))
        {
            $data = $this->redisGet($redis, $redis_key);
        }else {
            $sql = "SELECT id, title, func, icon, establishcost, ishavebanker, establishcoin, manymen, custombetscoin, betscoinlist, minbetcoin, maxbetcoin, overtime, state FROM rp_games WHERE `state`=1 ORDER BY `sort` ASC";
            $data = $db->query($sql);
            $this->redisSet($redis, $redis_key, $data);
        }
        return $data;
    }

    /***
     * 取游戏的参数及对应的赔率设置
     * @param $db 数据库连接对象
     * @param $gameid int 游戏的ID
     * @param $needuser int 需要参与的人数
     * @return array 游戏的参数及游戏对应的赔率设置
     */
    public function getGameAndOddsForGameID($redis, $db, $gameid, $needuser = 5)
    {
        $redis_key = $this->redisPrefix['GPOP'].$gameid.'_'.$needuser;
        if($redis->exists($redis_key))
        {
            $data = $this->redisGet($redis, $redis_key);
        }else {
            $sql = "SELECT id, title, func, establishcost, ishavebanker, establishcoin, manymen, custombetscoin, betscoinlist, minbetcoin, maxbetcoin, overtime, maxodds, state FROM rp_games WHERE id=" . $gameid . " ORDER BY `sort` ASC";
            $games = $db->row($sql);

            $sql = "SELECT * FROM `rp_games_odds` WHERE `gameid`=".$gameid." AND `manymen`=".$needuser." ORDER BY `winsort` DESC";
            $odds = $db->query($sql);

            $data = array(
                'game' => $games,
                'odds' => $odds,
            );

            $this->redisSet($redis, $redis_key, $data);
        }

        return $data;
    }

    //指定期数的红包 -- 用于展示
    public function getRedPacketForIssue($db,$issue)
    {
        $sql = "SELECT `id`,`need`,`begintimes`,`coin`,`gameid`,`overtime` FROM `rp_bets` WHERE `issue`='{$issue}' LIMIT 1";
        $data = $db->row($sql);
        $nowtime = time();
        $result = array(
            'id'=> $data['id'],
            'issue'=> $issue,
            'need' => $data['need'],
            'coin' => $data['coin'],
            'game' => $data['gameid'],
            'begintimes' => $data['begintimes'],
            'overtime' => ($data['begintimes'] + intval($data['overtime'])) - $nowtime,
        );
        return array($result);
    }

    #endregion

    #region 用户相关
    //生成用户号码
    public function makeUserNo($db)
    {
        $min_rand = 10000;
        $max_rand = 99999999;
        $uno = mt_rand($min_rand, $max_rand);
        $data = $db->query("SELECT `uid` FROM `rp_users` WHERE `uno`='{$uno}' LIMIT 1");
        if($data)
        {
            $this->makeUserNo($db);
        }else{
            return $uno;
        }
    }
    //生成token方法代码
    public function settoken($uno, $keys)
    {
        $str = md5($uno.(uniqid(md5(microtime(true)),true)).$keys);  //生成一个不会重复的字符串
        $str = sha1($str);  //加密
        return $str;
    }
    //验证帐号及token有效性
    public function exitsToKen($client_id, $paras, $isAutoLogin = true){
        //$username = self::existsKeyInArray('username',$paras,'S');
        $token =  self::existsKeyInArray('token',$paras,'S');
        $db = \GatewayWorker\Lib\Db::instance('db');
        $field = '`uid`,`uno`,`lastlogintimes`,`coin`,`nickname`,`avatar`,`usertype`';
        $where = "`webtoken`='{$token}'";
        $user = $db->row("SELECT {$field} FROM `rp_users` WHERE {$where} LIMIT 1");
        $lastlogintimes = intval($user['lastlogintimes']) + 300; //5分钟没有活动即退出
        $nowtime = time();
        $exitsToKen_result['state'] = 200;
        $exitsToKen_result['usercoin'] = 0;
        if(!$user){
            //登录的token失效，要重新登录了
            $exitsToKen_result['state'] = 301;
            $exitsToKen_result['msgid'] = 10002;
            return $exitsToKen_result;
        }
        if($lastlogintimes < $nowtime){
            //登录失效，要重新登录了
            $exitsToKen_result['state'] = 301;
            $exitsToKen_result['msgid'] = 10001;
            return $exitsToKen_result;
        }

        if($exitsToKen_result['state']==200){
            $exitsToKen_result['uid'] = $user['uid'];
            $exitsToKen_result['uno'] = $user['uno'];
            $exitsToKen_result['usercoin'] = $user['coin'];
            $exitsToKen_result['nickname'] = $user['nickname'];
            $exitsToKen_result['avatar'] = $user['avatar'];
            $exitsToKen_result['usertype'] = $user['usertype'];
            $exitsToKen_result['token'] = $token;
            if($isAutoLogin) {
                //绑定
                Gateway::bindUid($client_id, $user['uno']);
            }
            //更新token的有效时间
            $db->query("UPDATE `rp_users` SET `lastlogintimes`={$nowtime} WHERE `webtoken`='{$token}' LIMIT 1");
            //$db->update('rp_users')->cols(array('lastlogintimes'=>time()))->where(array("`webtoken`"=>$token))->query();
        }
        return $exitsToKen_result;
    }

    /**
     * 取出列表用户的余额数据并按用户的推送给玩家，
     * @param $db object 数据库连接对象
     * @param $users 需要推送的用户列表
     */
    public function sendToUidFreeCoinForIssue($db, $users)
    {
        //取出列表用户的余额数据并推送
        $ids = "0";
        foreach($users as $key=>$val)
        {
            $ids .= "," . $val['uid'];
        }
        $sql = "select `uno`,`coin` from `rp_users` where uid in({$ids})";
        $datas = $db->query($sql);
        $coins = array();
        foreach($datas as $key=>$val)
        {
            $coins[$val['uno']] = $val['coin'];
        }
        foreach($coins as $k=>$v)
        {
            $result_coins = array(
                'cmd' => 'updatecoin',
                'coin' => $v,
            );
            Gateway::sendToUid($k,json_encode($result_coins));
        }
    }

    /**
     * 用户帐变记录
     * @param $db
     * @param $log
     */
    public function setCoin($db,$log){
        //IN `uid` int,`gameid` int,`coin` float,`liqtype` int,`ex1` int,`ex2` varchar
        $default = array(
            'uid' => 0,
            'gameid' => 0,
            'coin' => 0,
            'liqtype' => 1,
            'ex1' => 0,
            'ex2' => '',
            'ex3' => '',
        );
        $sql = 'call setCoin(';
        foreach ($default as $k => $v) {
            $val = (array_key_exists($k, $log) && $log[$k]) ? $log[$k] : $v;
            if ($v !== 0) $val = "'$val'";
            $sql .= $val.',';
        }
        $sql = substr($sql, 0, -1).')';
        $db->query($sql);
    }

    /**
     * 取指定$token用户的余额
     */
    public function getUserCoin($db, $token)
    {
        $sql = "SELECT `coin` FROM `rp_users` WHERE `webtoken`='{$token}'";
        $data = $db->column($sql);
        $result = $data[0];
        if(empty($result)) $result = 0;
        return $result;
    }
    #endregion

    #region 聊天室
    /**
     * 生成当前游戏类型的期号
     * @param $db_id object 数据库对象
     * @param $game_id int 游戏类型
     * @return string
     */
    public function getChatRedIssue($redis, $db, $chatid){
        $redis_key = 'chat_issue_' . $chatid . '_count';
        $redis_key_date = 'chat_issue_' . $chatid . '_createdate';
        $issue_nums_len = 6;
        $issue_nums = 1000000; //要保留的期号长度,当前数字少一位数
        $nowdate = strval(date('Ymd'));
        # 如果Key存在且创建的日期是今天即从Redis缓存中取期数
        if($redis->exists($redis_key) && $nowdate==$redis->get($redis_key_date))
        {
            $redis_issue = $redis->get($redis_key);
            $_issue = substr($redis_issue,-1,$issue_nums_len);
            $sourceNumber = intval($_issue) + 1;
            $newNumber = substr(strval($sourceNumber + $issue_nums), 1, 6);
        }else {
            $beginTimes = mktime(0, 0, 0, date('m'), date('d'), date('Y'));
            $endTimes = $beginTimes + 86400;
            $sql = "SELECT (COUNT(1)+1) AS _TOTAL FROM `rp_rooms_red` WHERE `begintimes`>={$beginTimes} AND `begintimes`<={$endTimes} AND `chatid`={$chatid}";
            $issue_db = $db->row($sql);
            $sourceNumber = $issue_db['_TOTAL'];
            $newNumber = substr(strval($sourceNumber + $issue_nums), 1, 6);
        }
        $issue = date('Ymd') . $chatid . $newNumber;
        # 写入Redis
        $this->redisSet($redis, $redis_key, $issue);
        return $issue;
    }
    /**
     * 房间号参数转换(把chat_5或5统一转换成5)
     * @param $roomid string|int 房间号1 | chat_1
     * @return mixed
     */
    public function getRoomID($roomid)
    {
        $pos = strpos($roomid, 'chat');
        if ($pos !== false){
            $roomid = str_replace('chat_', '', $roomid);
        }
        return $roomid;
    }
    # 取所有可用的聊天室
    public function getChatList($redis, $db)
    {
        $redis_key = $this->redisPrefix['CRAS'];
        if($redis->exists($redis_key))
        {
            $data = $this->redisGet($redis, $redis_key);
        }else {
            $data = $db->select('`id`,`name`,`explain`,`icon`,`roomtype`')->from('rp_rooms')->where('state=1')->query();
            $this->redisSet($redis, $redis_key, $data);
        }
        return $data;
    }
	// 取单个聊天室的参数
    public function getRoomParas($redis, $db, $roomid)
    {
        $roomid = $this->getRoomID($roomid);
        $redis_key = $this->redisPrefix['CRLP'].$roomid;
        if($redis->exists($redis_key))
        {
            $data = $this->redisGet($redis, $redis_key);
        }else {
            $data = $db->row("SELECT * FROM `rp_rooms` WHERE `id`=" . $roomid);
            $this->redisSet($redis, $redis_key, $data);
        }
        return $data;
    }

    /**
     * 聊天室黑名单列表
     * @param $redis
     * @param $db
     * @param $roomid
     * @return mixed
     */
    public function chatBlacklist($redis, $db, $roomid)
    {
        $roomid = $this->getRoomID($roomid);
        $redis_key = $this->redisPrefix['CRBL'].$roomid;
        if($redis->exists($redis_key))
        {
            $data = $this->redisGet($redis, $redis_key);
        }else {
            $data = $db->query("SELECT `uno` FROM `rp_rooms_blacklist` WHERE `roomid`=" . $roomid);
            $this->redisSet($redis, $redis_key, $data);
        }
        return $data;
    }

    /**
     * 检测是否黑名单
     * @param $uno
     * @param $blacklist
     * @return bool
     */
    public function existsBlackUser($uno, $blacklist)
    {
        $isBlackUser = false;
        if(is_array($blacklist)) {
            //$arr2 = array_column($blacklist, 'uno'); //php版本必须 >= 5.5.0
            foreach ($blacklist as $k => $v) {
                if (strval($v['uno']) === strval($uno)) {
                    $isBlackUser = true;
                    break;
                }
            }
        }
        return $isBlackUser;
    }

    #endregion
}